package com.vois.jack.btmgr.devices.F1Dev;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.os.Bundle;
import android.os.Message;
import android.os.ParcelUuid;
import android.util.Log;

import com.vois.jack.btmgr.blebase.BleAction;
import com.vois.jack.btmgr.blebase.BleDevice;
import com.vois.jack.btmgr.blebase.BleDeviceFsm;
import com.vois.jack.btmgr.common.IBtConstants;
import com.vois.jack.btmgr.util.ActionProcessUtil;
import com.vois.jack.btmgr.util.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class F1BleDevice extends BleDevice implements Wl400BleDataPackage.Wl400BleReceiveMessage {
    private Logger logger = Logger.getLogger(F1BleDevice.class);
    private ActionProcessUtil actionProcessUtil;
    private Wl400BleDataPackage wl400BleDataPackage;
    private ArrayList<Wl400NetworkConfigData.Wl400WifiInfo> wl400WifiInfoList = new ArrayList<>();
    private boolean isWifiListGetCompleted;
    private List<byte[]> sendDataList;
    public static final String EXTRA_WIFI_INFO = "wifi_info";

    private ActionProcessUtil.ActionCallback actionCallback = new ActionProcessUtil.ActionCallback() {
        @Override
        public boolean onProcess(Object context, Bundle parameters) {
            logger.d( "onProcess: config wifi");
            if (sendDataList != null && sendDataList.size() > 0) {
                byte[] data = sendDataList.get(0);

                if (data != null) {
                    sendWriteAction(
                            UUID.fromString(Wl400NetworkConfigData.SERVICE_UUID),
                            UUID.fromString(Wl400NetworkConfigData.WRITE_CHARACTERISTIC_UUID),
                            data, data.length, new BleAction.BleActionCallback() {
                                @Override
                                public void onActionResult(int status, Bundle result) {
                                    if (status == BluetoothGatt.GATT_SUCCESS) {
                                        actionProcessUtil.reportResult(F1BleDevice.this, null);
                                    }else {
                                        actionProcessUtil.reportError(F1BleDevice.this, -1);
                                    }
                                    sendDataList.remove(0);
                                }
                            });
                    return true;
                }
            }

            return false;
        }

        @Override
        public void onResult(Object context, Bundle data) {
        }

        @Override
        public void onError(Object context, int errorCode) {
        }

        @Override
        public void onTimeout(Object context) {
        }
    };

    @Override
    public void onScanStateChanged(int state) {

    }

    @Override
    public void onVerifying() {

    }

    @Override
    public void getValidationData() {

    }

    @Override
    public void onError(int errorCause) {

    }

    @Override
    public void onCharacteristiChanged(UUID serviceUUID, UUID characteristicUUID, byte[] data) {
        if (wl400BleDataPackage == null) {
            wl400BleDataPackage = new Wl400BleDataPackage(getCurrentMTU(), this);
        }

        wl400BleDataPackage.onReceiveData(data);
    }

    @Override
    public void onReliableWriteCompleted(int status) {

    }

    public F1BleDevice() {
        super();
    }

    @Override
    public void onReady() {
        super.onReady();

        BleAction bleAction = new BleAction();
        Bundle args = new Bundle();
        args.putParcelable(BleDeviceFsm.EXTRA_SERVICE_UUID, new ParcelUuid(UUID.fromString(Wl400NetworkConfigData.SERVICE_UUID)));
        args.putParcelable(BleDeviceFsm.EXTRA_CHARACTERISTIC_UUID, new ParcelUuid(UUID.fromString(Wl400NetworkConfigData.READ_CHARACTERISTIC_UUID)));
        args.putBoolean(BleDeviceFsm.EXTRA_ENABLE_VALUE, true);
        bleAction.setCmd(BleAction.BleCmd.BLE_CMD_ENABLE_NOTIFICATION);
        bleAction.setCmdArg(args);
        bleAction.setCallback(new BleAction.BleActionCallback() {
            @Override
            public void onActionResult(int status, Bundle result) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    setMtu(Wl400NetworkConfigData.WL400_BLE_MTU);
                }
            }
        });

        getBleDeviceFsm().executeBleAction(bleAction);
    }

    private void setMtu(int mtu) {
        negotiateMTU(mtu, new BleAction.BleActionCallback() {
            @Override
            public void onActionResult(int status, Bundle result) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    setCurrentMTU(result.getInt(BleDeviceFsm.EXTRA_MTU_VALUE));
                }else {
                    setCurrentMTU(Wl400NetworkConfigData.WL400_DEFAULT_BLE_MTU);
                }

                if (wl400BleDataPackage == null) {
                    wl400BleDataPackage = new Wl400BleDataPackage(getCurrentMTU(), F1BleDevice.this);
                }
            }
        });
    }

    @Override
    public void onInited() {
        super.onInited();
        actionProcessUtil = new ActionProcessUtil("F1BleDevice", getBleDeviceFsm().getHandler());
        actionProcessUtil.startActionExecution();
    }

    @Override
    public void onFsmStopped() {
        super.onFsmStopped();
        actionProcessUtil.stopActionExecution();
        actionProcessUtil = null;
        isWifiListGetCompleted = false;
        wl400WifiInfoList.clear();
        setCurrentMTU(Wl400NetworkConfigData.WL400_DEFAULT_BLE_MTU);

        if(wl400BleDataPackage != null){
            wl400BleDataPackage.reset();
            wl400BleDataPackage = null;
        }
    }

    @Override
    public void onNotify(int type, String jsonStr) {
        BleDeviceListener listener = getListener();
        if(type == Wl400NetworkConfigData.NOTIFY_WIFI_INFO_TYPE){
            Wl400NetworkConfigData.Wl400WifiInfo wl400WifiInfo = wl400BleDataPackage.getWl400WifiInfoByJsonStr(jsonStr);
            if (wl400WifiInfo != null) {
                wl400WifiInfoList.add(wl400WifiInfo);
                if (listener != null) {
                    Message message = Message.obtain();
                    Bundle bundle = new Bundle();
                    message.what = F1BleMsg.F1BLE_GET_WIFI_INFO_MSG.getValue();
                    bundle.putSerializable(EXTRA_WIFI_INFO, wl400WifiInfo);
                    message.setData(bundle);
                    listener.onMessage(getBluetoothDevice(), message);
                }
            }
        }else if(type == Wl400NetworkConfigData.NOTIFY_SEND_WIFI_LIST_COMPLETED_TYPE){
            isWifiListGetCompleted = true;
            if (listener != null) {
                Message message = Message.obtain();
                message.what = F1BleMsg.F1BLE_GET_WIFI_LIST_COMPLETED_MSG.getValue();
                listener.onMessage(getBluetoothDevice(), message);
            }
        }
    }

    @Override
    public void onResponse(int type) {
        logger.d( "onResponse: type:" + type);
        BleDeviceListener listener = getListener();
        if(Wl400NetworkConfigData.GET_WIFI_LIST_TYPE == type){
            if (listener != null) {
                Message message = Message.obtain();
                message.what = F1BleMsg.F1BLE_GET_WIFI_LIST_ACK_MSG.getValue();
                listener.onMessage(getBluetoothDevice(), message);
            }
        }else if(Wl400NetworkConfigData.ADD_WIFI_CONFIG_TYPE == type){
            if (listener != null) {
                Message message = Message.obtain();
                message.what = F1BleMsg.F1BLE_ADD_WIFI_CONFIG_ACK_MSG.getValue();
                listener.onMessage(getBluetoothDevice(), message);
            }
        }else if(Wl400NetworkConfigData.MODIFY_AP_CONFIG_TYPE == type){
            if (listener != null) {
                Message message = Message.obtain();
                message.what = F1BleMsg.F1BLE_MODIFY_AP_CONFIG_ACK_MSG.getValue();
                listener.onMessage(getBluetoothDevice(), message);
            }
        }
    }

    @Override
    public void onRequest(int type, String jsonStr) {

    }

    public void configWIFI(int configType, String name, String password) {
        if (wl400BleDataPackage == null) {
            wl400BleDataPackage = new Wl400BleDataPackage(getCurrentMTU(), this);
        }

        sendDataList = wl400BleDataPackage.getWl400ConfigData(configType, new Wl400NetworkConfigData.Wl400NetworkConfigInfo(name, password));
        actionProcessUtil.addActionRequest(this, null, 15000, actionCallback);
    }

    public List<Wl400NetworkConfigData.Wl400WifiInfo> getWl400WifiInfoList() {
        return wl400WifiInfoList;
    }

    public boolean isWifiListGetCompleted() {
        return isWifiListGetCompleted;
    }

    @Override
    public String getDeviceModel() {
        return "WL-F1 Serial";
    }

    @Override
    public void setSeqID(String seqID) {
    }

    @Override
    public void getVendor() {
    }

    @Override
    public void getVersion() {
    }

    @Override
    public String getProtocolName() {
        return IBtConstants.PROTOCOL_VOIS;
    }
}
